package com.ikan.positionserver.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ikan.positionserver.dto.*;
import com.ikan.positionserver.entity.Device;
import com.ikan.positionserver.entity.Rack;
import com.ikan.positionserver.entity.RackColumn;
import com.ikan.positionserver.entity.Room;
import com.ikan.positionserver.enums.RackTypeEnum;
import com.ikan.positionserver.enums.UnitTypeEnum;
import com.ikan.positionserver.mapper.RoomMapper;
import com.ikan.positionserver.service.*;
import com.ikan.positionserver.util.DtoConvertor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 机房 服务实现类
 * </p>
 *
 * @author ikan
 * @since 2024-04-10
 */
@Slf4j
@Service
public class RoomServiceImpl extends ServiceImpl<RoomMapper, Room> implements IRoomService {
    @Autowired
    private IRackColumnService rackColumnService;
    @Autowired
    private IRackService rackService;
    @Autowired
    private IDeviceUnitService deviceUnitService;


    @Autowired
    private IDeviceService deviceService;

    @Override
    public RoomDto getRoomAllInfo(String name) {
        QueryWrapper<Room> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name", name);
        List<Room> roomList = list(queryWrapper);
        if (CollectionUtils.isEmpty(roomList)) {
            return null;
        }
        Room room = roomList.get(0);
        RoomDto roomDto = DtoConvertor.convert2Dto(room);
        fillRackColumn(roomDto);

        return roomDto;
    }

    @Override
    public RoomDto getBriefRoom(String name) {
        QueryWrapper<Room> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name", name);
        List<Room> roomList = list(queryWrapper);
        if (CollectionUtils.isEmpty(roomList)) {
            return null;
        }
        Room room = roomList.get(0);
        RoomDto roomDto = DtoConvertor.convert2Dto(room);
        fillRackColumnBrief(roomDto);

        return roomDto;
    }

    private void fillRackColumnBrief(RoomDto roomDto) {
        QueryWrapper<RackColumn> rackColumnQueryWrapper = new QueryWrapper<>();
        rackColumnQueryWrapper.eq("room_id", roomDto.getId());
        List<RackColumn> rackColumnList = rackColumnService.list(rackColumnQueryWrapper);
        List<RackColumnDto> rackColumnDtoList = DtoConvertor.convertRackColumn2DtoList(rackColumnList);
        roomDto.setRackColumnList(rackColumnDtoList);

        for (RackColumnDto rackColumnDto : rackColumnDtoList) {
            fillRackBrief(rackColumnDto);
        }
    }

    private void fillRackColumn(RoomDto roomDto) {
        QueryWrapper<RackColumn> rackColumnQueryWrapper = new QueryWrapper<>();
        rackColumnQueryWrapper.eq("room_id", roomDto.getId());
        List<RackColumn> rackColumnList = rackColumnService.list(rackColumnQueryWrapper);
        List<RackColumnDto> rackColumnDtoList = DtoConvertor.convertRackColumn2DtoList(rackColumnList);
        roomDto.setRackColumnList(rackColumnDtoList);

        for (RackColumnDto rackColumnDto : rackColumnDtoList) {
            fillRack(rackColumnDto);
        }
    }
    private void fillRackBrief(RackColumnDto rackColumnDto) {
        QueryWrapper<Rack> rackQueryWrapper = new QueryWrapper<>();
        log.info("查询列的机柜:{}", rackColumnDto);
        rackQueryWrapper.eq("column_id", rackColumnDto.getId());

        rackQueryWrapper.orderByAsc("hole_id");
        List<Rack> rackList = rackService.list(rackQueryWrapper);
        log.info("查询到列的机柜数量:{}", rackList.size());
        List<RackDto> rackDtoList = DtoConvertor.convertRackList2Dto(rackList);
        rackColumnDto.setRackDtoList(rackDtoList);

    }

    private void fillRack(RackColumnDto rackColumnDto) {
        QueryWrapper<Rack> rackQueryWrapper = new QueryWrapper<>();
        log.info("查询列的机柜:{}", rackColumnDto);
        rackQueryWrapper.eq("column_id", rackColumnDto.getId());

        rackQueryWrapper.orderByAsc("hole_id");
        List<Rack> rackList = rackService.list(rackQueryWrapper);
        log.info("查询到列的机柜数量:{}", rackList.size());
        List<RackDto> rackDtoList = DtoConvertor.convertRackList2Dto(rackList);
        rackColumnDto.setRackDtoList(rackDtoList);

        for (RackDto rackDto : rackDtoList) {
            fillServerUnit(rackDto);
        }
    }

    private void fillServerUnit(RackDto rackDto) {
//        QueryWrapper<ServerUnit> serverUnitQueryWrapper = new QueryWrapper<>();
//        log.info("查询机柜:{}", rackDto);
//        serverUnitQueryWrapper.eq("rack_id", rackDto.getId());
//        serverUnitQueryWrapper.orderByAsc("seq ");
//        List<ServerUnit> serverUnitList = serverUnitService.list(serverUnitQueryWrapper);
//        log.info("查询到U的数量:{}", serverUnitList.size());
//        List<ServerUnitDto> serverUnitDtoList = DtoConvertor.convertServerUnitList2Dto(serverUnitList);
//        rackDto.setServerUnitDtoList(serverUnitDtoList);

        //2024.4.12: 直接构造U位信息
        RackTypeEnum rackTypeEnum = RackTypeEnum.getByCode(rackDto.getRackType());

//        rackDto.setServerUnitDtoList(serverUnitDtoList);
        if (rackTypeEnum == RackTypeEnum.RACK) {
            List<DeviceUnitVO> deviceUnitVOList = fillServer(rackDto);
            rackDto.setDeviceUnitVOList(deviceUnitVOList);
        }
    }

    private List<DeviceUnitVO> fillServer(RackDto rackDto) {
        QueryWrapper<Device> serverQueryWrapper = new QueryWrapper<>();
//        log.info("查询列的机柜:{}", rackDto);
        serverQueryWrapper.eq("rack_id", rackDto.getId());
        serverQueryWrapper.orderByAsc("u_start_id");
        List<Device> deviceList = deviceService.list(serverQueryWrapper);
        //存放所有的服务器
        Map<Integer, Device> mapRackAllServer = getDeviceMap(deviceList);
        //存放已经存在的服务器
        Map<Integer, Device> mapMergeUnitDevice = Maps.newHashMap();

        List<DeviceUnitVO> deviceUnitVOList = Lists.newArrayList();
        List<RackUnitDto> rackUnitDtoList = getRackUnitDtoList(rackDto);

        //所有的机柜
        for (RackUnitDto rackUnitDto : rackUnitDtoList) {
            int uStartId = rackUnitDto.getUStartId();
//            log.info("uStartId:{}", uStartId);
            //首先判断服务器是否存在
            if (mapRackAllServer.containsKey(uStartId)) {
                DeviceUnitVO deviceUnitVO = new DeviceUnitVO();
                deviceUnitVO.setSeq(rackUnitDto.getUStartId());
                deviceUnitVO.setRackId(rackDto.getId());
                deviceUnitVO.setUStartId(rackUnitDto.getUStartId());
                deviceUnitVO.setHeight(rackUnitDto.getHeight());
                deviceUnitVO.setRackName(rackDto.getName());
                //接着判断服务器占用多个U位
                if (mapMergeUnitDevice.containsKey(uStartId) == false) {
                    deviceUnitVO.setUnitType(UnitTypeEnum.Server.getCode());
                    Device device = mapRackAllServer.get(uStartId);
                    deviceUnitVO.setDevice(device);
                    deviceUnitVO.setShow(true);

                    //将服务器放到当前map中
                    int startUnit = device.getUStartId();
                    int height = device.getHeight();
                    int endUnit = startUnit + height;
                    log.info("put unit in mapMergeUnitServer, startUnit:{}, endUnit:{}, device:{}", startUnit, endUnit, device);
                    for (int i = startUnit; i < endUnit; i++) {
                        mapMergeUnitDevice.put(i, device);
                    }
                } else {
                    deviceUnitVO.setShow(false);
                    deviceUnitVO.setUnitType(UnitTypeEnum.MergeUnit.getCode());
                }
                deviceUnitVOList.add(deviceUnitVO);
            } else {
                //如果存在
                DeviceUnitVO deviceUnitVO = new DeviceUnitVO();
                deviceUnitVO.setSeq(uStartId);
                deviceUnitVO.setShow(true);
                deviceUnitVO.setRackId(rackDto.getId());
                deviceUnitVO.setUStartId(rackUnitDto.getUStartId());
                deviceUnitVO.setHeight(rackUnitDto.getHeight());
                deviceUnitVO.setRackName(rackDto.getName());
                deviceUnitVO.setUnitType(UnitTypeEnum.Empty.getCode());
                deviceUnitVOList.add(deviceUnitVO);
            }

        }
        //再倒一次，顺过来
        Collections.reverse(deviceUnitVOList);
        return deviceUnitVOList;
    }

    private Map<Integer, Device> getDeviceMap(List<Device> serverList) {
        Map<Integer, Device> mapDevice = Maps.newHashMap();
        for (Device device : serverList) {
            log.info("存放服务器, device:{}", device);
            int startUnit = device.getUStartId();
            int height = device.getHeight();
            int endUnit = startUnit + height;
            for (int i = startUnit; i < endUnit; i++) {
                mapDevice.put(i, device);
            }
        }
        return mapDevice;
    }

    private List<RackUnitDto> getRackUnitDtoList(RackDto rackDto) {
        List<RackUnitDto> rackUnitDtoList = Lists.newArrayList();
        int rackUnitCount = 45;
        for (int i = 1; i < rackUnitCount; i++) {
            RackUnitDto rackUnitDto = new RackUnitDto();
            int uStartId = rackUnitCount - i;
            rackUnitDto.setSeq(uStartId);
            rackUnitDto.setRackId(rackDto.getId());
            rackUnitDto.setRackName(rackDto.getName());
            rackUnitDto.setUStartId(uStartId);
            rackUnitDto.setHeight(1);
            rackUnitDtoList.add(rackUnitDto);
        }
        //倒序一下
        Collections.reverse(rackUnitDtoList);
        return rackUnitDtoList;
    }
}
